#pragma once
#include <iostream>
#include <string>
#include <cassert>
#include <cstring>

using namespace std;
namespace lmr
{
    class string
    {
    public:

        using iterator = char*;
        using const_iterator = const char*;

        iterator begin() noexcept
        {
            return _str;
        }

        iterator end() noexcept
        {
            return _str + _size;
        }

        const_iterator begin() const noexcept
        {
            return _str;
        }

        const_iterator end() const noexcept
        {
            return _str + _size;
        }
        
        const_iterator cbegin() const noexcept
        {
            return _str;
        }
        const_iterator cend() const noexcept
        {
            return _str + _size;
        }



        string(const char* str = "")
        {
            _size = strlen(str);
            //_capacity不包括\0
            _capacity = _size;
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }

        string(const string& s)
        {
            _str = new char[s._capacity + 1];
            strcpy(_str, s._str);
            _size = s._size;
            _capacity = s._capacity;
        }

        ~string()
        {
            delete[] _str;
            _str = nullptr;
            _size = _capacity = 0;
        }

        const char* c_str() const noexcept
        {
            return _str;
        }

        
        const char* data() const noexcept
        {
            return _str;
        }

        char* data() noexcept
        {
            return _str;
        }
        
        void clear()
        {
            _str[0] = '\0';
            _size = 0;
        }

        const size_t size() const noexcept
        {
            return _size;
        }

        const size_t capacity() const noexcept
        {
            return _capacity;
        }

        char& operator[](size_t pos)
        {
            assert(pos < _size);
            return _str[pos];
        }

        const char& operator[](size_t pos) const
        {
            assert(pos < _size);
            return _str[pos];
        }

        string& operator=(const string& s)
        {
            if(this != &s)
            {
                delete[] _str;
                _str = new char[s._capacity + 1];
                strcpy(_str, s._str);
                _size = s._size;
                _capacity = s._capacity;
            }
            return *this;
        }

        void reserve(size_t n);
		void push_back(char ch);
		void append(const char* str);
		string& operator+=(char ch);
		string& operator+=(const char* str);
		string& operator+=(const string& str);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos, size_t len = npos);

        size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);
		string substr(size_t pos = 0, size_t len = npos);

    private:
        char* _str = nullptr;
        size_t _size;
        size_t _capacity;
        //特殊用法const int 类型的static全局变量才可以这样用
        // static const size_t npos = -1; 
        static const size_t npos;

    };

    bool operator<(const string& s1, const string& s2);
	bool operator<=(const string& s1, const string& s2);
	bool operator>(const string& s1, const string& s2);
	bool operator>=(const string& s1, const string& s2);
	bool operator==(const string& s1, const string& s2);
	bool operator!=(const string& s1, const string& s2);

    istream& getline(istream& in, string& s);
	ostream& operator<<(ostream& out, const string& s);
	istream& operator>>(istream& in, string& s);
}